Instead of always mirroring the selection to a single PRIMARY selection,
authorOwen Taylor <otaylor@redhat.com>
Fri, 31 Aug 2001 01:33:11 +0000 (01:33 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Fri, 31 Aug 2001 01:33:11 +0000 (01:33 +0000)
Wed Aug 29 20:40:58 2001  Owen Taylor  <otaylor@redhat.com>

        * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard):
        Instead of always mirroring the selection to a single PRIMARY
        selection, allow it to be mirrored to any number of clipboards.

        * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove,
        just use gtk_text_buffer_paste_clipboard with the appropriate clipboard.

        * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a
        GtkClipboard argument, and for paste_clipboard, the
        @override_location argument from @paste_primary.

        * gtk/gtktextview.c: Adapt to above change.

ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtktextbuffer.c
gtk/gtktextbuffer.h
gtk/gtktextview.c

index 5579b2634b53b80f0a56a11a97f48d459d561765..ecf5313b2a3ab5d47728e367e4db43a0e8f0f701 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Wed Aug 29 20:40:58 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): 
+       Instead of always mirroring the selection to a single PRIMARY
+       selection, allow it to be mirrored to any number of clipboards.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, 
+       just use gtk_text_buffer_paste_clipboard with the appropriate clipboard.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a
+       GtkClipboard argument, and for paste_clipboard, the
+       @override_location argument from @paste_primary.
+
+       * gtk/gtktextview.c: Adapt to above change.
+       
 2001-08-30  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktextview.c (invalidated_handler): put validate idle at
index 5579b2634b53b80f0a56a11a97f48d459d561765..ecf5313b2a3ab5d47728e367e4db43a0e8f0f701 100644 (file)
@@ -1,3 +1,18 @@
+Wed Aug 29 20:40:58 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): 
+       Instead of always mirroring the selection to a single PRIMARY
+       selection, allow it to be mirrored to any number of clipboards.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, 
+       just use gtk_text_buffer_paste_clipboard with the appropriate clipboard.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a
+       GtkClipboard argument, and for paste_clipboard, the
+       @override_location argument from @paste_primary.
+
+       * gtk/gtktextview.c: Adapt to above change.
+       
 2001-08-30  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktextview.c (invalidated_handler): put validate idle at
index 5579b2634b53b80f0a56a11a97f48d459d561765..ecf5313b2a3ab5d47728e367e4db43a0e8f0f701 100644 (file)
@@ -1,3 +1,18 @@
+Wed Aug 29 20:40:58 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): 
+       Instead of always mirroring the selection to a single PRIMARY
+       selection, allow it to be mirrored to any number of clipboards.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, 
+       just use gtk_text_buffer_paste_clipboard with the appropriate clipboard.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a
+       GtkClipboard argument, and for paste_clipboard, the
+       @override_location argument from @paste_primary.
+
+       * gtk/gtktextview.c: Adapt to above change.
+       
 2001-08-30  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktextview.c (invalidated_handler): put validate idle at
index 5579b2634b53b80f0a56a11a97f48d459d561765..ecf5313b2a3ab5d47728e367e4db43a0e8f0f701 100644 (file)
@@ -1,3 +1,18 @@
+Wed Aug 29 20:40:58 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): 
+       Instead of always mirroring the selection to a single PRIMARY
+       selection, allow it to be mirrored to any number of clipboards.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, 
+       just use gtk_text_buffer_paste_clipboard with the appropriate clipboard.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a
+       GtkClipboard argument, and for paste_clipboard, the
+       @override_location argument from @paste_primary.
+
+       * gtk/gtktextview.c: Adapt to above change.
+       
 2001-08-30  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktextview.c (invalidated_handler): put validate idle at
index 5579b2634b53b80f0a56a11a97f48d459d561765..ecf5313b2a3ab5d47728e367e4db43a0e8f0f701 100644 (file)
@@ -1,3 +1,18 @@
+Wed Aug 29 20:40:58 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): 
+       Instead of always mirroring the selection to a single PRIMARY
+       selection, allow it to be mirrored to any number of clipboards.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, 
+       just use gtk_text_buffer_paste_clipboard with the appropriate clipboard.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a
+       GtkClipboard argument, and for paste_clipboard, the
+       @override_location argument from @paste_primary.
+
+       * gtk/gtktextview.c: Adapt to above change.
+       
 2001-08-30  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktextview.c (invalidated_handler): put validate idle at
index 5579b2634b53b80f0a56a11a97f48d459d561765..ecf5313b2a3ab5d47728e367e4db43a0e8f0f701 100644 (file)
@@ -1,3 +1,18 @@
+Wed Aug 29 20:40:58 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): 
+       Instead of always mirroring the selection to a single PRIMARY
+       selection, allow it to be mirrored to any number of clipboards.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, 
+       just use gtk_text_buffer_paste_clipboard with the appropriate clipboard.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a
+       GtkClipboard argument, and for paste_clipboard, the
+       @override_location argument from @paste_primary.
+
+       * gtk/gtktextview.c: Adapt to above change.
+       
 2001-08-30  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktextview.c (invalidated_handler): put validate idle at
index 5579b2634b53b80f0a56a11a97f48d459d561765..ecf5313b2a3ab5d47728e367e4db43a0e8f0f701 100644 (file)
@@ -1,3 +1,18 @@
+Wed Aug 29 20:40:58 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_add/remove_selection_clipboard): 
+       Instead of always mirroring the selection to a single PRIMARY
+       selection, allow it to be mirrored to any number of clipboards.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_paste_primary): Remove, 
+       just use gtk_text_buffer_paste_clipboard with the appropriate clipboard.
+
+       * gtk/gtktextbuffer.[ch] (gtk_text_buffer_cut/copy/paste_clipboard): Add a
+       GtkClipboard argument, and for paste_clipboard, the
+       @override_location argument from @paste_primary.
+
+       * gtk/gtktextview.c: Adapt to above change.
+       
 2001-08-30  Havoc Pennington  <hp@redhat.com>
 
        * gtk/gtktextview.c (invalidated_handler): put validate idle at
index 12f36373e8c6eba43190ee91f519b65a7be59ecf..df584961aa6f91538383436343cee2b1cd211415 100644 (file)
@@ -81,7 +81,6 @@ static void gtk_text_buffer_class_init (GtkTextBufferClass *klass);
 static void gtk_text_buffer_finalize   (GObject            *object);
 
 
-static void gtk_text_buffer_update_primary_selection   (GtkTextBuffer     *buffer);
 static void gtk_text_buffer_real_insert_text           (GtkTextBuffer     *buffer,
                                                         GtkTextIter       *iter,
                                                         const gchar       *text,
@@ -108,6 +107,10 @@ static void gtk_text_buffer_real_changed               (GtkTextBuffer     *buffe
 static GtkTextBTree* get_btree (GtkTextBuffer *buffer);
 static void          free_log_attr_cache (GtkTextLogAttrCache *cache);
 
+static void remove_all_clipboard_contents_buffers (GtkTextBuffer *buffer);
+static void remove_all_selection_clipboards       (GtkTextBuffer *buffer);
+static void update_selection_clipboards           (GtkTextBuffer *buffer);
+
 static GtkObjectClass *parent_class = NULL;
 static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -299,7 +302,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass)
 void
 gtk_text_buffer_init (GtkTextBuffer *buffer)
 {
-  buffer->clipboard_contents = NULL;
+  buffer->clipboard_contents_buffers = NULL;
 }
 
 /**
@@ -334,12 +337,9 @@ gtk_text_buffer_finalize (GObject *object)
 
   buffer = GTK_TEXT_BUFFER (object);
 
-  if (buffer->clipboard_contents)
-    {
-      g_object_unref (G_OBJECT (buffer->clipboard_contents));
-      buffer->clipboard_contents = NULL;
-    }
-  
+  remove_all_clipboard_contents_buffers (buffer);
+  remove_all_selection_clipboards (buffer);
+
   if (buffer->tag_table)
     {
       g_object_unref (G_OBJECT (buffer->tag_table));
@@ -1116,7 +1116,7 @@ gtk_text_buffer_real_delete_range (GtkTextBuffer *buffer,
   _gtk_text_btree_delete (start, end);
 
   /* may have deleted the selection... */
-  gtk_text_buffer_update_primary_selection (buffer);
+  update_selection_clipboards (buffer);
 
   g_signal_emit (G_OBJECT (buffer), signals[CHANGED], 0);
 }
@@ -1586,7 +1586,7 @@ gtk_text_buffer_set_mark (GtkTextBuffer *buffer,
   if (_gtk_text_btree_mark_is_insert (get_btree (buffer), mark) ||
       _gtk_text_btree_mark_is_selection_bound (get_btree (buffer), mark))
     {
-      gtk_text_buffer_update_primary_selection (buffer);
+      update_selection_clipboards (buffer);
     }
 
   _gtk_text_btree_get_iter_at_mark (get_btree (buffer),
@@ -2588,6 +2588,87 @@ clipboard_get_selection_cb (GtkClipboard     *clipboard,
     }
 }
 
+typedef struct
+{
+  GtkClipboard *clipboard;
+  GtkTextBuffer *buffer;
+} ContentsBuffer;
+
+static void
+remove_all_clipboard_contents_buffers (GtkTextBuffer *buffer)
+{
+  GSList *tmp_list = buffer->clipboard_contents_buffers;
+  while (tmp_list)
+    {
+      ContentsBuffer *contents_buffer = tmp_list->data;
+
+      g_object_unref (contents_buffer->buffer);
+      g_free (contents_buffer);
+         
+      tmp_list = tmp_list->next;
+    }
+
+  g_slist_free (buffer->clipboard_contents_buffers);
+  buffer->clipboard_contents_buffers = NULL;
+}
+
+static void
+remove_clipboard_contents_buffer (GtkTextBuffer *buffer,
+                                 GtkClipboard  *clipboard)
+{
+  GSList *tmp_list = buffer->clipboard_contents_buffers;
+  while (tmp_list)
+    {
+      ContentsBuffer *contents_buffer = tmp_list->data;
+      
+      if (contents_buffer->clipboard == clipboard)
+       {
+         buffer->clipboard_contents_buffers = g_slist_remove (buffer->clipboard_contents_buffers, contents_buffer);
+         
+         g_object_unref (contents_buffer->buffer);
+         g_free (contents_buffer);
+         
+         return;
+       }
+
+      tmp_list = tmp_list->next;
+    }
+}
+
+static GtkTextBuffer *
+get_clipboard_contents_buffer (GtkTextBuffer *buffer,
+                              GtkClipboard  *clipboard,
+                              gboolean       create)
+{
+  ContentsBuffer *contents_buffer;
+  GSList *tmp_list;
+
+  tmp_list = buffer->clipboard_contents_buffers;
+  while (tmp_list)
+    {
+      contents_buffer = tmp_list->data;
+      if (contents_buffer->clipboard == clipboard)
+       return contents_buffer->buffer;
+    }
+  
+  if (create)
+    {
+      contents_buffer = g_new (ContentsBuffer, 1);
+      contents_buffer->clipboard = clipboard;
+      contents_buffer->buffer = gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer));
+
+      g_object_set_data (G_OBJECT (contents_buffer->buffer), "gtk-text-buffer-clipboard",
+                        GUINT_TO_POINTER (1));
+
+      buffer->clipboard_contents_buffers = g_slist_prepend (buffer->clipboard_contents_buffers, contents_buffer);
+
+      
+      return contents_buffer->buffer;
+    }
+  else
+    return NULL;
+}
+
 /* Provide cut/copied data */
 static void
 clipboard_get_contents_cb (GtkClipboard     *clipboard,
@@ -2596,7 +2677,9 @@ clipboard_get_contents_cb (GtkClipboard     *clipboard,
                            gpointer          data)
 {
   GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
-  GtkTextBuffer *contents = buffer->clipboard_contents;
+  GtkTextBuffer *contents = get_clipboard_contents_buffer (buffer, clipboard, FALSE);
+
+  g_assert (contents); /* This should never be called unless we own the clipboard */
 
   if (selection_data->target ==
       gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
@@ -2612,25 +2695,16 @@ clipboard_get_contents_cb (GtkClipboard     *clipboard,
     }
   else
     {
-      /* Just provide text from the clipboard buffer */
-      if (buffer->clipboard_contents)
-        {
-          gchar *str;
-          GtkTextIter start, end;
-          
-          gtk_text_buffer_get_bounds (contents, &start, &end);
-          /* strip off the trailing newline, it isn't part of the text that was cut */
-          gtk_text_iter_backward_char (&end);
-          
-          str = gtk_text_iter_get_visible_text (&start, &end);
-          gtk_selection_data_set_text (selection_data, str);
-          g_free (str);
-        }
-      else
-        {
-          gtk_selection_data_set_text (selection_data, "");
-          return;
-        }
+      gchar *str;
+      GtkTextIter start, end;
+      
+      gtk_text_buffer_get_bounds (contents, &start, &end);
+      /* strip off the trailing newline, it isn't part of the text that was cut */
+      gtk_text_iter_backward_char (&end);
+      
+      str = gtk_text_iter_get_visible_text (&start, &end);
+      gtk_selection_data_set_text (selection_data, str);
+      g_free (str);
     }
 }
 
@@ -2640,11 +2714,7 @@ clipboard_clear_contents_cb (GtkClipboard *clipboard,
 {
   GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
 
-  if (buffer->clipboard_contents)
-    {
-      g_object_unref (G_OBJECT (buffer->clipboard_contents));
-      buffer->clipboard_contents = NULL;
-    }  
+  remove_clipboard_contents_buffer (buffer, clipboard);
 }
 
 static void
@@ -2849,39 +2919,21 @@ clipboard_clipboard_buffer_received (GtkClipboard     *clipboard,
     {
       GtkTextIter start, end;
 
-      gtk_text_buffer_get_bounds (src_buffer, &start, &end);
-      /* There's an extra newline on clipboard_contents */
-      gtk_text_iter_backward_char (&end);
+      if (g_object_get_data (G_OBJECT (src_buffer), "gtk-text-buffer-clipboard"))
+       {
+         gtk_text_buffer_get_bounds (src_buffer, &start, &end);
+         /* There's an extra newline on clipboard_contents */
+         gtk_text_iter_backward_char (&end);
       
-      paste_from_buffer (request_data, src_buffer,
-                         &start, &end);
-    }
-  else
-    {
-      /* Request the text selection instead */
-      gtk_clipboard_request_text (clipboard,
-                                  clipboard_text_received,
-                                  data);
-    }
-}
-
-static void
-clipboard_selection_buffer_received (GtkClipboard     *clipboard,
-                                     GtkSelectionData *selection_data,
-                                     gpointer          data)
-{
-  ClipboardRequest *request_data = data;
-  GtkTextBuffer *src_buffer;
-  
-  src_buffer = selection_data_get_buffer (selection_data, request_data); 
-
-  if (src_buffer)
-    {
-      GtkTextIter start, end;
-
-      if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end))
-        paste_from_buffer (request_data, src_buffer,
-                           &start, &end);
+         paste_from_buffer (request_data, src_buffer,
+                            &start, &end);
+       }
+      else
+       {
+         if (gtk_text_buffer_get_selection_bounds (src_buffer, &start, &end))
+           paste_from_buffer (request_data, src_buffer,
+                              &start, &end);
+       }
     }
   else
     {
@@ -2900,49 +2952,179 @@ static const GtkTargetEntry targets[] = {
   { "GTK_TEXT_BUFFER_CONTENTS", 0, TARGET_TEXT_BUFFER_CONTENTS }
 };
 
+typedef struct
+{
+  GtkClipboard *clipboard;
+  guint ref_count;
+} SelectionClipboard;
+
 static void
-gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer)
+update_selection_clipboards (GtkTextBuffer *buffer)
 {
-  GtkTextIter start;
-  GtkTextIter end;
+  GSList *tmp_list = buffer->selection_clipboards;
+  while (tmp_list)
+    {
+      GtkTextIter start;
+      GtkTextIter end;
+      
+      SelectionClipboard *selection_clipboard = tmp_list->data;
+      GtkClipboard *clipboard = selection_clipboard->clipboard;
 
-  GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+      /* Determine whether we have a selection and adjust X selection
+       * accordingly.
+       */
+      if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+       {
+         if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer))
+           gtk_clipboard_clear (clipboard);
+       }
+      else
+       {
+         /* Even if we already have the selection, we need to update our
+          * timestamp.
+          */
+         if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
+                                            clipboard_get_selection_cb,
+                                            clipboard_clear_selection_cb,
+                                            G_OBJECT (buffer)))
+           clipboard_clear_selection_cb (clipboard, buffer);
+       }
 
-  /* Determine whether we have a selection and adjust X selection
-   * accordingly.
-   */
+      tmp_list = tmp_list->next;
+    }
+}
 
-  if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+static SelectionClipboard *
+find_selection_clipboard (GtkTextBuffer *buffer,
+                         GtkClipboard  *clipboard)
+{
+  GSList *tmp_list = buffer->selection_clipboards;
+  while (tmp_list)
+    {
+      SelectionClipboard *selection_clipboard = tmp_list->data;
+      if (selection_clipboard->clipboard == clipboard)
+       return selection_clipboard;
+      
+      tmp_list = tmp_list->next;
+    }
+
+  return NULL;
+}
+
+/**
+ * gtk_text_buffer_add_selection_clipboard:
+ * @buffer: a #GtkTextBuffer
+ * @clipboard: a #GtkClipboard
+ * 
+ * Adds @clipboard to the list of clipboards in which the selection contents
+ * of @buffer are available. In most cases, @clipboard will be the #GtkClipboard
+ * of type %GDK_SELECTION_PRIMARY for a view of @buffer.
+ **/
+void
+gtk_text_buffer_add_selection_clipboard (GtkTextBuffer *buffer,
+                                        GtkClipboard  *clipboard)
+{
+  SelectionClipboard *selection_clipboard;
+
+  g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  g_return_if_fail (clipboard != NULL);
+
+  selection_clipboard = find_selection_clipboard (buffer, clipboard);
+  if (selection_clipboard)
     {
-      if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer))
-        gtk_clipboard_clear (clipboard);
+      selection_clipboard->ref_count++;
     }
   else
     {
-      /* Even if we already have the selection, we need to update our
-       * timestamp.
-       */
-      if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
-                                         clipboard_get_selection_cb,
-                                         clipboard_clear_selection_cb,
-                                         G_OBJECT (buffer)))
-        clipboard_clear_selection_cb (clipboard, buffer);
+      selection_clipboard = g_new (SelectionClipboard, 1);
+
+      selection_clipboard->clipboard = clipboard;
+      selection_clipboard->ref_count = 1;
+
+      buffer->selection_clipboards = g_slist_prepend (buffer->selection_clipboards, selection_clipboard);
+    }
+}
+
+/**
+ * gtk_text_buffer_remove_selection_clipboard:
+ * @buffer: a #GtkTextBuffer
+ * @clipboard: a #GtkClipboard added to @buffer by gtk_text_buffer_add_selection_clipboard().
+ * 
+ * Removes a #GtkClipboard added with gtk_text_buffer_add_selection_clipboard()
+ **/
+void 
+gtk_text_buffer_remove_selection_clipboard (GtkTextBuffer *buffer,
+                                           GtkClipboard  *clipboard)
+{
+  SelectionClipboard *selection_clipboard;
+
+  g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  g_return_if_fail (clipboard != NULL);
+
+  selection_clipboard = find_selection_clipboard (buffer, clipboard);
+  g_return_if_fail (selection_clipboard != NULL);
+
+  selection_clipboard->ref_count--;
+  if (selection_clipboard->ref_count == 0)
+    {
+      if (gtk_clipboard_get_owner (selection_clipboard->clipboard) == G_OBJECT (buffer))
+       gtk_clipboard_clear (selection_clipboard->clipboard);
+      
+      g_free (selection_clipboard);
     }
 }
 
 static void
-paste (GtkTextBuffer *buffer,
-       gboolean       is_clipboard,
-       gboolean       interactive,
-       gboolean       default_editable)
+remove_all_selection_clipboards (GtkTextBuffer *buffer)
+{
+  GSList *tmp_list = buffer->selection_clipboards;
+  while (tmp_list)
+    {
+      SelectionClipboard *selection_clipboard = tmp_list->data;
+      
+      if (gtk_clipboard_get_owner (selection_clipboard->clipboard) == G_OBJECT (buffer))
+       gtk_clipboard_clear (selection_clipboard->clipboard);
+      
+      g_free (selection_clipboard);
+
+      tmp_list = tmp_list->next;
+    }
+
+  g_slist_free (buffer->selection_clipboards);
+  buffer->selection_clipboards = NULL;
+}
+
+/**
+ * gtk_text_buffer_paste_clipboard:
+ * @buffer: a #GtkTextBuffer
+ * @clipboard: the #GtkClipboard to paste from
+ * @override_location: location to insert pasted text, or %NULL for at the cursor
+ * @default_editable: whether the buffer is editable by default
+ *
+ * Pastes the contents of a clipboard at the insertion point, or at @override_location.
+ * (Note: pasting is asynchronous, that is, we'll ask for the paste data and
+ * return, and at some point later after the main loop runs, the paste
+ * data will be inserted.)
+ * 
+ **/
+void
+gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
+                                GtkClipboard  *clipboard,
+                                GtkTextIter   *override_location,
+                                 gboolean       default_editable)
 {
   ClipboardRequest *data = g_new (ClipboardRequest, 1);
   GtkTextIter paste_point;
   GtkTextIter start, end;
-  
+
+  if (override_location != NULL)
+    gtk_text_buffer_create_mark (buffer,
+                                 "gtk_paste_point_override",
+                                 override_location, FALSE);
+
   data->buffer = buffer;
   g_object_ref (G_OBJECT (buffer));
-  data->interactive = interactive;
+  data->interactive = TRUE;
   data->default_editable = default_editable;
 
   /* When pasting with the cursor inside the selection area, you
@@ -2959,58 +3141,9 @@ paste (GtkTextBuffer *buffer,
        gtk_text_iter_equal (&paste_point, &end)))
     data->replace_selection = TRUE;
 
-  if (is_clipboard)
-    gtk_clipboard_request_contents (gtk_clipboard_get (GDK_NONE),
-                                    
-                                    gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
-                                    clipboard_clipboard_buffer_received, data);
-  else
-    gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
-                                    
-                                    gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
-                                    clipboard_selection_buffer_received, data);    
-}
-
-/**
- * gtk_text_buffer_paste_primary:
- * @buffer: a #GtkTextBuffer 
- * @override_location: location to insert pasted text, or %NULL for at the cursor
- * @default_editable: whether the buffer is editable by default 
- * 
- * Pastes the primary selection at the insertion point, or at @override_location.
- * (Note: pasting is asynchronous, that is, we'll ask for the paste data
- * and return, and at some point later after the main loop runs, the paste
- * data will be inserted.)
- **/
-void
-gtk_text_buffer_paste_primary (GtkTextBuffer       *buffer,
-                               const GtkTextIter   *override_location,
-                               gboolean             default_editable)
-{
-  if (override_location != NULL)
-    gtk_text_buffer_create_mark (buffer,
-                                 "gtk_paste_point_override",
-                                 override_location, FALSE);
-
-  paste (buffer, FALSE, TRUE, default_editable);
-}
-
-/**
- * gtk_text_buffer_paste_clipboard:
- * @buffer: a #GtkTextBuffer 
- * @default_editable: whether the buffer is editable by default
- *
- * Pastes the clipboard contents at the insertion point.  (Note:
- * pasting is asynchronous, that is, we'll ask for the paste data and
- * return, and at some point later after the main loop runs, the paste
- * data will be inserted.)
- * 
- **/
-void
-gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
-                                 gboolean       default_editable)
-{
-  paste (buffer, TRUE, TRUE, default_editable);
+  gtk_clipboard_request_contents (clipboard,
+                                 gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE),
+                                 clipboard_clipboard_buffer_received, data);
 }
 
 /**
@@ -3055,9 +3188,10 @@ gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
 
 static void
 cut_or_copy (GtkTextBuffer *buffer,
-             gboolean delete_region_after,
-             gboolean interactive,
-             gboolean default_editable)
+            GtkClipboard  *clipboard,
+             gboolean       delete_region_after,
+             gboolean       interactive,
+             gboolean       default_editable)
 {
   /* We prefer to cut the selected region between selection_bound and
    * insertion point. If that region is empty, then we cut the region
@@ -3068,12 +3202,8 @@ cut_or_copy (GtkTextBuffer *buffer,
    */
   GtkTextIter start;
   GtkTextIter end;
-  
-  if (buffer->clipboard_contents)
-    {
-      g_object_unref (G_OBJECT (buffer->clipboard_contents));
-      buffer->clipboard_contents = NULL;
-    }
+
+  remove_clipboard_contents_buffer (buffer, clipboard);
   
   if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
     {
@@ -3091,19 +3221,14 @@ cut_or_copy (GtkTextBuffer *buffer,
 
   if (!gtk_text_iter_equal (&start, &end))
     {
-      GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
       GtkTextIter ins;
+      GtkTextBuffer *contents;
       
-      buffer->clipboard_contents =
-        gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer));
+      contents = get_clipboard_contents_buffer (buffer, clipboard, TRUE);
 
-      gtk_text_buffer_get_iter_at_offset (buffer->clipboard_contents,
-                                          &ins, 0);
+      gtk_text_buffer_get_iter_at_offset (contents, &ins, 0);
       
-      gtk_text_buffer_insert_range (buffer->clipboard_contents,
-                                    &ins,
-                                    &start,
-                                    &end);
+      gtk_text_buffer_insert_range (contents, &ins, &start, &end);
                                     
       if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
                                          clipboard_get_contents_cb,
@@ -3124,34 +3249,38 @@ cut_or_copy (GtkTextBuffer *buffer,
 
 /**
  * gtk_text_buffer_cut_clipboard:
- * @buffer: a #GtkTextBuffer 
+ * @buffer: a #GtkTextBuffer
+ * @clipboard: the #GtkClipboard object to cut to.
  * @default_editable: default editability of the buffer
  *
- * Copies the currently-selected text to the clipboard, then deletes
+ * Copies the currently-selected text to a clipboard, then deletes
  * said text if it's editable.
  * 
  **/
 void
 gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
+                              GtkClipboard  *clipboard,
                                gboolean       default_editable)
 {
   gtk_text_buffer_begin_user_action (buffer);
-  cut_or_copy (buffer, TRUE, TRUE, default_editable);
+  cut_or_copy (buffer, clipboard, TRUE, TRUE, default_editable);
   gtk_text_buffer_end_user_action (buffer);
 }
 
 /**
  * gtk_text_buffer_copy_clipboard:
  * @buffer: a #GtkTextBuffer 
+ * @clipboard: the #GtkClipboard object to copy to.
  *
- * Copies the currently-selected text to the clipboard.
+ * Copies the currently-selected text to a clipboard.
  * 
  **/
 void
-gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer)
+gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer,
+                               GtkClipboard  *clipboard)
 {
   gtk_text_buffer_begin_user_action (buffer);
-  cut_or_copy (buffer, FALSE, TRUE, TRUE);
+  cut_or_copy (buffer, clipboard, FALSE, TRUE, TRUE);
   gtk_text_buffer_end_user_action (buffer);
 }
 
index bfaafd2206fccfb3f31b778bffd6e28f87954a00..24311f8885e2a0d570eb60c67e83a9aa9ebfbd5e 100644 (file)
@@ -28,6 +28,7 @@
 #define GTK_TEXT_BUFFER_H
 
 #include <gtk/gtkwidget.h>
+#include <gtk/gtkclipboard.h>
 #include <gtk/gtktexttagtable.h>
 #include <gtk/gtktextiter.h>
 #include <gtk/gtktextmark.h>
@@ -62,7 +63,8 @@ struct _GtkTextBuffer
   GtkTextTagTable *tag_table;
   GtkTextBTree *btree;
 
-  GtkTextBuffer *clipboard_contents;
+  GSList *clipboard_contents_buffers;
+  GSList *selection_clipboards;
 
   GtkTextLogAttrCache *log_attr_cache;
 
@@ -324,13 +326,19 @@ gboolean        gtk_text_buffer_get_modified            (GtkTextBuffer *buffer);
 void            gtk_text_buffer_set_modified            (GtkTextBuffer *buffer,
                                                          gboolean       setting);
 
-void            gtk_text_buffer_paste_primary           (GtkTextBuffer       *buffer,
-                                                         const GtkTextIter   *override_location,
-                                                         gboolean             default_editable);
+void gtk_text_buffer_add_selection_clipboard    (GtkTextBuffer     *buffer,
+                                                GtkClipboard      *clipboard);
+void gtk_text_buffer_remove_selection_clipboard (GtkTextBuffer     *buffer,
+                                                GtkClipboard      *clipboard);
+
 void            gtk_text_buffer_cut_clipboard           (GtkTextBuffer *buffer,
+                                                        GtkClipboard  *clipboard,
                                                          gboolean       default_editable);
-void            gtk_text_buffer_copy_clipboard          (GtkTextBuffer *buffer);
+void            gtk_text_buffer_copy_clipboard          (GtkTextBuffer *buffer,
+                                                        GtkClipboard  *clipboard);
 void            gtk_text_buffer_paste_clipboard         (GtkTextBuffer *buffer,
+                                                        GtkClipboard  *clipboard,
+                                                        GtkTextIter   *override_location,
                                                          gboolean       default_editable);
 
 gboolean        gtk_text_buffer_get_selection_bounds    (GtkTextBuffer *buffer,
index 71a3e1c4697c67cedcbce5be54b8243ab820e886..3c10bbbc545f1197babc1f953127601b9455e67e 100644 (file)
@@ -1050,6 +1050,10 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
                                             gtk_text_view_mark_set_handler, text_view);
       g_object_unref (G_OBJECT (text_view->buffer));
       text_view->dnd_mark = NULL;
+
+      if (GTK_WIDGET_REALIZED (text_view))
+       gtk_text_buffer_remove_selection_clipboard (text_view->buffer,
+                                                   gtk_clipboard_get (GDK_SELECTION_PRIMARY));
     }
 
   text_view->buffer = buffer;
@@ -1077,6 +1081,10 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
 
       g_signal_connect (G_OBJECT (text_view->buffer), "mark_set",
                        G_CALLBACK (gtk_text_view_mark_set_handler), text_view);
+
+      if (GTK_WIDGET_REALIZED (text_view))
+       gtk_text_buffer_remove_selection_clipboard (text_view->buffer,
+                                                   gtk_clipboard_get (GDK_SELECTION_PRIMARY));
     }
 
   if (GTK_WIDGET_VISIBLE (text_view))
@@ -2939,6 +2947,10 @@ gtk_text_view_realize (GtkWidget *widget)
                          widget->window);
 
   gtk_text_view_ensure_layout (text_view);
+
+  if (text_view->buffer)
+    gtk_text_buffer_add_selection_clipboard (text_view->buffer,
+                                            gtk_clipboard_get (GDK_SELECTION_PRIMARY));
 }
 
 static void
@@ -2948,6 +2960,10 @@ gtk_text_view_unrealize (GtkWidget *widget)
   
   text_view = GTK_TEXT_VIEW (widget);
 
+  if (text_view->buffer)
+    gtk_text_buffer_remove_selection_clipboard (text_view->buffer,
+                                               gtk_clipboard_get (GDK_SELECTION_PRIMARY));
+
   if (text_view->first_validate_idle)
     {
       g_source_remove (text_view->first_validate_idle);
@@ -3290,9 +3306,10 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
                                              event->x + text_view->xoffset,
                                              event->y + text_view->yoffset);
 
-          gtk_text_buffer_paste_primary (get_buffer (text_view),
-                                         &iter,
-                                         text_view->editable);
+          gtk_text_buffer_paste_clipboard (get_buffer (text_view),
+                                          gtk_clipboard_get (GDK_SELECTION_PRIMARY),
+                                          &iter,
+                                          text_view->editable);
           return TRUE;
         }
       else if (event->button == 3)
@@ -4170,7 +4187,9 @@ gtk_text_view_delete_from_cursor (GtkTextView   *text_view,
 static void
 gtk_text_view_cut_clipboard (GtkTextView *text_view)
 {
-  gtk_text_buffer_cut_clipboard (get_buffer (text_view), text_view->editable);
+  gtk_text_buffer_cut_clipboard (get_buffer (text_view),
+                                gtk_clipboard_get (GDK_NONE),
+                                text_view->editable);
   DV(g_print (G_STRLOC": scrolling onscreen\n"));
   gtk_text_view_scroll_mark_onscreen (text_view,
                                       gtk_text_buffer_get_mark (get_buffer (text_view),
@@ -4180,7 +4199,8 @@ gtk_text_view_cut_clipboard (GtkTextView *text_view)
 static void
 gtk_text_view_copy_clipboard (GtkTextView *text_view)
 {
-  gtk_text_buffer_copy_clipboard (get_buffer (text_view));
+  gtk_text_buffer_copy_clipboard (get_buffer (text_view),
+                                 gtk_clipboard_get (GDK_NONE));
   DV(g_print (G_STRLOC": scrolling onscreen\n"));
   gtk_text_view_scroll_mark_onscreen (text_view,
                                       gtk_text_buffer_get_mark (get_buffer (text_view),
@@ -4190,7 +4210,10 @@ gtk_text_view_copy_clipboard (GtkTextView *text_view)
 static void
 gtk_text_view_paste_clipboard (GtkTextView *text_view)
 {
-  gtk_text_buffer_paste_clipboard (get_buffer (text_view), text_view->editable);
+  gtk_text_buffer_paste_clipboard (get_buffer (text_view),
+                                  gtk_clipboard_get (GDK_NONE),
+                                  NULL,
+                                  text_view->editable);
   DV(g_print (G_STRLOC": scrolling onscreen\n"));
   gtk_text_view_scroll_mark_onscreen (text_view,
                                       gtk_text_buffer_get_mark (get_buffer (text_view),